/**ChartLibrary**/


/*
Variable: paper
Keeps the Paper.
*/
var paper;

/*
Variable: org
init the Joint Diagram
*/

var org = Joint.dia.org;

/*
Variable: canvasWidth
Keeps canvas width.
*/



/*
Variable: canvasHeight
Keeps canvas height.
*/



var instance = null;

/*
    Class: ChartLibrary
    A class that manages Chart Functions
*/
var ChartLibrary =
{

    /*
    Function: initCanvas

    inti the SVG Drawing Canvas.

    Parameters:

    id - <div> tag which canvas is draw.
    w - Canvas width
    h - Canvas height


    Returns:

    Returns true if canvas init successfully.

    */
    initCanvas: function (id, w, h) {
        this.canvasWidth = w;
        this.canvasHeight = h;
        Joint.paper(id, this.canvasWidth, this.canvasHeight);

        /*gets the paper from JointJS lib.*/
        //this.paper = Joint.getPaper();
    },

    /*
    Function: arrangeData

    Arrange employee data for generating the tree 

    Parameters:

    strData - Data for the organizational chart

    Returns: Returns the arranged data

    */
    arrangeData: function (arrEmpArray) {
        if (arrEmpArray == undefined || arrEmpArray == null || arrEmpArray.length == 0)
            return null;

        var arrTemp = arrEmpArray
        arrEmpArray = arrTemp.sort(function (a, b) { return parseInt(a.WorkLevelId) - parseInt(b.WorkLevelId) });
        arrTemp = null;

        var arrNewEmp = [];

        for (var i = 0; i < arrEmpArray.length; i++) {
            var item = arrEmpArray[i];
            var emp =
                  { id: item.EmpId,
                      EmpId: item.EmpId,
                      name: item.CallName,
                      Designation: item.DesignationName + ' at',
                      image: item.Image,
                      level: item.WorkLevelId,
                      parent: item.Supervisor,
                      WorkLevelName: item.WorkLevelName,
                      EmpURL: item.EmpURL,
                      DesignationURL: item.DesignationURL,
                      CompanyURL: item.CompanyURL,
                      Grade: item.Grade,
                      EPFNumber: item.EPFNumber,
                      CompanyName: item.CompanyName,
                      IndirectReporting: item.IndirectReporting,
                      StartX: 0,
                      X: 0,
                      Y: 0,
                      PointX1: 0,
                      PointY1: 0,
                      PointX2: 0,
                      PointY2: 0,
                      MinChildWidth: 0,
                      SubNodes: 0,
                      Hidden: false,
                      NodeOrder: 0,
                      children: []
                  };

            arrNewEmp.push(emp);
        }

        return arrNewEmp;
    },
    /*
    Function: generateTree

    inti the SVG Drawing Canvas.

    Parameters:

    treeData - Tree Node

    Returns:

    Returns true if canvas init successfully.

    */
    generateTree: function (arrEmp, compactView, boxWidth, boxHeight, minHorizontalSpace, verticalSpace) {
        arrEmp = this.arrangeData(arrEmp);
        instance = new Tree();
        instance.compactView = compactView;
        instance.boxWidth = compactView ? boxWidth - instance.avatarHeight : boxWidth; //250        
        instance.boxHeight = compactView ? boxHeight - 50 : boxHeight; //130
        instance.minHorizontalSpace = minHorizontalSpace; //50
        instance.verticalSpace = verticalSpace; //50
        instance.parseData(arrEmp);
        instance.levelHeight = instance.boxHeight + instance.verticalSpace;
        instance.canvasWidth = instance.boxWidth;
        instance.canvasHeight = instance.boxHeight;
        instance.totalWidth = instance.canvasWidth;
        instance.totalHeight = instance.canvasHeight;
        instance.tree[0].MinChildWidth = instance.boxWidth + instance.minHorizontalSpace;
        instance.tree[0].StartX = 0;
        instance.tree[0].X = instance.tree[0].MinChildWidth / 2;
        instance.setLevel(1);
        instance.calculateWidth(instance.tree[0]);
        instance.CalculateX(instance.tree[0]);
        instance.totalWidth += instance.boxWidth / 2;
        instance.canvasWidth += instance.boxWidth / 2;
    },


    /*
    Function: drawTree

    Draw the tree with the provided instance

    Parameters: None

    Returns: Draws the Tree

    */
    drawTree: function () {
        this.drawNodes(instance.tree[0]);
    },



    /*
    Function: inti the SVG Drawing Canvas.

    Node Object which will be created on canvas

    Parameters:

    nodeItem - node

    Returns:

    Returns Created Node object from Raphael.js.

    */
    CreateNode: function (nodeItem) {

        var node = org.Member.create({
            rect: nodeItem.positionInfo,
            name: nodeItem.name,
            designation: nodeItem.designation,
            company: nodeItem.company,
            indirectReporting: nodeItem.indirectReporting,
            grade: nodeItem.grade,
            workLevel: nodeItem.workLevel,
            avatar: nodeItem.avatar,
            empURL: nodeItem.empURL,
            designationURL: nodeItem.designationURL,
            companyURL: nodeItem.companyURL,
            attrs: nodeItem.style,
            compactView: instance.compactView,
            avatarHeight: instance.avatarHeight
        }).draggable(false);

        return node;
    },


    /*
    Function: MakeAncestorsOf

    Create Relationships :   Ancestors of node n are all the nodes that are on some path  to n from root

    Parameters:

    Parent - Parent Node
    Child - Ch ild Node
    Label - Relationship label
    IsHighlight - is Relationship is Highlighted

    */
    MakeAncestorsOf: function (Parent, Child, Label, IsHighlight) {
        !0 == IsHighlight ? Child.joint(Parent, org.flower).label(Label).straighten().highlight() : Child.joint(Parent, org.flower).label(Label).straighten();
    },


    /*
    Function: drawNodes

    Draw tree nodes

    Parameters:

    node - node to draw in the canvas

    Returns:

    Draws the node object in svg canvas

    */
    drawNodes: function (node) {
        var boxWidth = node.Hidden ? 1 : instance.boxWidth;
        var boxHeight = node.Hidden ? 1 : instance.boxHeight;
        var style = node.Hidden ? STYLE.HIDDENSTYLE : STYLE.PARENTSTYLE;
        //        if (node.level > 4 && node.hidden != false)
        //            style = STYLE.CHILDSTYLE;
        node.name = node.Hidden ? null : node.EPFNumber + ' : ' + node.name;
        //        node.Designation = node.Hidden ? null : node.Designation;
        var nodeitem = new Node({ x: node.X, y: node.Y, width: boxWidth, height: boxHeight }, node.name, node.Designation, node.CompanyName, node.IndirectReporting, node.Grade, node.WorkLevelName, style, node.image, node.EmpURL, node.DesignationURL, node.CompanyURL);
        this.CreateNode(nodeitem);

        var nodes = node.children;
        if (nodes.length > 0) {
            for (var i = 0; i < nodes.length; i++) {
                this.drawNodes(nodes[i]);

                //var parent = node.Hidden ? instance.getVisibleParent(node.parent) : node;
                var parent = node;

                if (!nodes[i].Hidden) {

                    Joint({ x: nodes[i].PointX1, y: nodes[i].PointY1 + 0.5 }, { x: parent.PointX2, y: parent.PointY2 + -1 }, {
                        startArrow: { type: 'none', size: 0, attrs: {} },
                        endArrow: { type: 'none', size: 0, attrs: {} },
                        attrs: { 'stroke-dasharray': '1', 'stroke-width': 0.9, stroke: 'black', fill: 'black' },
                        interactive: false,
                        cursor: 'default'
                    });

                } else {

                    Joint({ x: nodes[i].PointX1 + 0.5, y: nodes[i].PointY1 + 0.5 }, { x: parent.PointX2, y: parent.PointY2 + -1 }, {
                        startArrow: {
                            type: "square",
                            size: 0.1,
                            attrs: { stroke: "gray", fill: "gray"}
                        },
                        endArrow: {
                            type: "none",
                            size: 0, 
                            attrs: {}
                        },
                        attrs: { 'stroke-dasharray': '1', 'stroke-width': 0.9, stroke: 'black', fill: 'black' },
                        interactive: false,
                        cursor: 'default'
                    });
                }

            }
        }
    }
};


/*
Function: Joint.arrows.square

Draw square arrow

Parameters:

size - size of the object

Returns:

Draws the node head object in svg canvas

*/
Joint.arrows.square = function (size) {
    size = size.toString();
    return {
        path: ["M", size, size,
               "L", size, size,
               "L", size, size,
               "L", size, size, "z"],
        dx: size,
        dy: 0,
        attrs: {
            stroke: "gray",
            fill: "gray"
        },
        interactive: false,
        cursor: 'default'
    };
};


/*
Class: Node
    A class data strecture for the node object
*/
function Node(positionInfo, name, designation, company, indirectReporting, grade, workLevel, style, avatar, empURL, designationURL, companyURL) {
    this.name = name,
    this.designation = designation,
    this.company = company,
    this.indirectReporting = indirectReporting,
    this.grade = grade,
    this.workLevel = workLevel,
    this.avatar = avatar,
    this.empURL = empURL,
    this.companyURL = companyURL,
    this.designationURL = designationURL,
    this.positionInfo = positionInfo,
    this.style = style
 };


 /*
 Class: Rectangle
 A class data strecture for the Rectangle
 */
function Rectangle(x, y, w, h){
    this.x=x;
    this.y=y;
    this.w=w;
    this.h=h;
};


/*
Function: Support Objects

Draw square arrow

Parameters:

size - size of the object

Returns:

Draws the node head object in svg canvas

*/

var STYLE = {
    PARENTSTYLE: {
        fill: '#C7DCF1',
        stroke: '#554C75'        
    },
    CHILDSTYLE: {
        fill: '#AEA5CF',
        stroke:'#554C75'
    },
    HIDDENSTYLE: {
        fill: '#4192d3',
        stroke: 'white'
    }
}